﻿using System;
using System.Threading;

namespace Sunny.FrameDecoder;

/// <summary>
/// 通讯基类
/// </summary>
public abstract class BaseSocket : IDisposable
{
    private long _bytesReceived = 0;
    private long _bytesSent = 0;
#if DEBUG
    private ConsoleLogger _logger = new ConsoleLogger(LogLevel.Off);
#else
    private ConsoleLogger _logger = new ConsoleLogger(LogLevel.Debug);
#endif

    private long _flow;
    private ValueCountTimer _counter = new ValueCountTimer() { Period = TimeSpan.FromSeconds(1) };

    /// <summary>
    /// 初始化参数
    /// </summary>
    protected virtual void Init()
    {
        _counter.Tick = v => { _flow = v; };
        Name = GetType().Name;
    }

    /// <summary>
    /// 接收数据字节数
    /// </summary>
    public long BytesReceived => _bytesReceived;

    /// <summary>
    /// 发送数据字节数
    /// </summary>
    public long BytesSent => _bytesSent;

    /// <summary>
    /// 最后发送时间
    /// </summary>
    public DateTime LastSentTime { get; set; } = DateTime.MinValue;

    /// <summary>
    /// 最后接收时间
    /// </summary>
    public DateTime LastReceivedTime { get; set; } = DateTime.MinValue;

    /// <summary>
    /// 日志级别
    /// </summary>
    public LogLevel LogLevel
    {
        get => _logger.Level;
        set => _logger.Level = value;
    }

    /// <summary>
    /// 控制台日志记录
    /// </summary>
    public ConsoleLogger Logger => _logger;

    /// <summary>
    /// 名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 标签
    /// </summary>
    public object Tag { get; set; }

    /// <summary>
    /// 析构函数
    /// </summary>
    public abstract void Dispose();

    /// <summary>
    /// 每秒流量（字节/秒）
    /// </summary>
    public long Flow => (DateTime.Now - LastSentTime) < TimeSpan.FromSeconds(2) || (DateTime.Now - LastReceivedTime) < TimeSpan.FromSeconds(2) ? _flow : 0;

    /// <summary>
    /// 每秒流量
    /// </summary>
    public string FlowString => ToFlowString(Flow);

    /// <summary>
    /// 增加接收数据字节数统计
    /// </summary>
    /// <param name="bytesCount">字节数</param>
    public void AddReceivedBytes(long bytesCount)
    {
        Interlocked.Add(ref _bytesReceived, bytesCount);
        LastReceivedTime = DateTime.Now;
        _counter.Add(bytesCount);
    }

    /// <summary>
    /// 增加发送数据字节数统计
    /// </summary>
    /// <param name="bytesCount">字节数</param>
    public void AddSentBytes(long bytesCount)
    {
        Interlocked.Add(ref _bytesSent, bytesCount);
        LastSentTime = DateTime.Now;
        _counter.Add(bytesCount);
    }

    private string ToFlowString(long flow)
    {
        if (flow < 1000) return $"{flow}B/s";
        if (flow < 1000 * 1000) return $"{(flow / 1024.0).ToString("F2")}KB/s";
        if (flow < 1000 * 1000 * 1000) return $"{(flow / 1024.0 / 1024.0).ToString("F2")}MB/s";
        return $"{flow}B/s";
    }

    /// <summary>
    /// 字符串是否为IP地址
    /// </summary>
    /// <param name="s">字符串</param>
    /// <returns>结果</returns>
    protected bool IsIP4(string s)
    {
        string[] strs = s.Split('.');
        if (strs.Length != 4)
        {
            return false;
        }

        foreach (string str in strs)
        {
            if (int.TryParse(str, out int value))
            {
                if (value < 0) return false;
                if (value > 255) return false;
            }
        }

        return true;
    }

    /// <summary>
    /// 接收数据状态
    /// </summary>
    /// <param name="span">时间间隔</param>
    /// <returns>在指定时间间隔内是否接收到数据</returns>
    public bool ReceiveStatus(TimeSpan span) => DateTime.Now - LastReceivedTime < span;
}
